package com.haifeng.jupiter.common.log.aop;

import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;
import com.haifeng.jupiter.common.log.annotation.GlobalLog;
import com.haifeng.jupiter.common.log.constants.GlobalLogConstants;
import com.haifeng.jupiter.common.log.entity.GlobalLogEntity;
import com.haifeng.jupiter.common.log.event.GlobalLogEvent;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * <p>
 *  全局操作日志AOP
 * </p>
 *
 * @author: Haifeng
 * @date: 2020-08-09
 */
@Slf4j
@Aspect
@Component
@AllArgsConstructor
public class GlobalLogAop {

	private final ApplicationEventPublisher publisher;

	@SneakyThrows
	@Around("@annotation(globalLog)")
	public Object around(ProceedingJoinPoint point, GlobalLog globalLog) {
		String strClassName = point.getTarget().getClass().getName();
		String strMethodName = point.getSignature().getName();
		Object[] args = point.getArgs();
		log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName);
		HttpServletRequest request = ((ServletRequestAttributes) Objects
				.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
		GlobalLogEntity globalLogEntity = new GlobalLogEntity();
		globalLogEntity.setRemoteAddr(ServletUtil.getClientIP(request));
		globalLogEntity.setRequestUri(URLUtil.getPath(request.getRequestURI()));
		globalLogEntity.setMethod(request.getMethod());
		globalLogEntity.setParams(JSONUtil.toJsonStr(args));
		globalLogEntity.setTitle(globalLog.value());
		globalLogEntity.setType(GlobalLogConstants.NORMAL);
		globalLogEntity.setCreateUserName("");
		// 发送异步日志事件
		Long startTime = System.currentTimeMillis();
		Object obj = point.proceed();
		Long endTime = System.currentTimeMillis();
		globalLogEntity.setTime(endTime - startTime);
		publisher.publishEvent(new GlobalLogEvent(globalLogEntity));
		return obj;
	}

}
